package com.digitalchina.lxnsy.base;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;

import android.net.Uri;
import android.widget.ImageView;

import com.apkfuns.logutils.LogLevel;
import com.apkfuns.logutils.LogUtils;
import com.baidu.mapapi.SDKInitializer;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.digitalchina.lxnsy.R;
import com.digitalchina.lxnsy.constant.TIME;
import com.digitalchina.lxnsy.constant.URL;
import com.digitalchina.lxnsy.entity.ApkUpdateVO;
import com.digitalchina.lxnsy.service.LocationService;
import com.digitalchina.lxnsy.toolkit.FastJsonUtil;
import com.digitalchina.lxnsy.toolkit.ToastUtil;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.liulishuo.filedownloader.FileDownloader;
import com.lzy.imagepicker.loader.ImageLoader;
import com.lzy.ninegrid.NineGridView;
import com.lzy.okhttputils.OkHttpUtils;
import com.mob.MobSDK;
import com.raizlabs.android.dbflow.config.FlowConfig;
import com.raizlabs.android.dbflow.config.FlowManager;

import org.lzh.framework.updatepluginlib.UpdateConfig;
import org.lzh.framework.updatepluginlib.callback.UpdateCheckCB;
import org.lzh.framework.updatepluginlib.callback.UpdateDownloadCB;
import org.lzh.framework.updatepluginlib.model.CheckEntity;
import org.lzh.framework.updatepluginlib.model.HttpMethod;
import org.lzh.framework.updatepluginlib.model.Update;
import org.lzh.framework.updatepluginlib.model.UpdateParser;
import org.lzh.framework.updatepluginlib.util.Utils;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import cn.jpush.android.api.JPushInterface;


/**
 * ================================================
 * 项目名称：bigdata
 * 类描述：
 * 包名：com.digitalchina.bigdata.base
 * 创建人：白彦东
 * 创建时间：2016/10/10 15:47
 * 修改备注：
 * ================================================
 */

public class BaseApplication extends MultiDexApplication {

    public LocationService locationService;

    private boolean isDeBug = true;  // 生产版-false   开发版-true

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        closeAndroidPDialog();

        initOkHttpUtils();
        initLogUtils();
        initDBFlow();
        Fresco.initialize(getApplicationContext());
        FileDownloader.init(getApplicationContext());
        MobSDK.init(getApplicationContext());
        initBaiduLBS();

        initJPush();

        NineGridView.setImageLoader(new PicassoImageLoader());

    }


    /**
     * 调研了一下，是 Android P 后谷歌限制了开发者调用非官方公开API 方法或接口，也就是说，你用反射直接调用源码就会有这样的提示弹窗出现，
     * 非 SDK 接口指的是 Android 系统内部使用、并未提供在 SDK 中的接口，开发者可能通过 Java 反射、JNI 等技术来调用这些接口。
     * 但是，这么做是很危险的：非 SDK 接口没有任何公开文档，必须查看源代码才能理解其行为逻辑。
     */
    private void closeAndroidPDialog(){
        try {
            Class aClass = Class.forName("android.content.pm.PackageParser$Package");
            Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Class cls = Class.forName("android.app.ActivityThread");
            Method declaredMethod = cls.getDeclaredMethod("currentActivityThread");
            declaredMethod.setAccessible(true);
            Object activityThread = declaredMethod.invoke(null);
            Field mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown");
            mHiddenApiWarningShown.setAccessible(true);
            mHiddenApiWarningShown.setBoolean(activityThread, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * Toast
     */
    private void showToast(String msg) {
        ToastUtil.showToast(getApplicationContext(), msg);
    }

    /**
     * Apk 更新配置
     */
    private void initApkUpdateConfig() {
        // 建议在Application中进行配置。
        // UpdateConfig为全局配置。当在其他页面中。使用UpdateBuilder进行检查更新时。
        // 对于没传的参数，会默认使用UpdateConfig中的全局配置
        UpdateConfig.getConfig()
                // url 与 checkEntity方法可任选一种填写，且至少必填一种。
                // 数据更新接口数据，此时默认为使用GET请求
//                .url(URL.SERVER + URL.URL_GET_APK_UPDATE_URL)
                // 类似url方法。CheckEntity方法可填写url,params,method。可在此设置为使用post请求
                .checkEntity(new CheckEntity().setMethod(HttpMethod.POST).setUrl(URL.URL_GET_APK_UPDATE_URL))
                // 必填：用于从数据更新接口获取的数据response中。解析出Update实例。以便框架内部处理
                .jsonParser(new UpdateParser() {
                    @Override
                    public Update parse(String response) {
                        // 此处根据上面url接口返回的数据response进行update类组装。框架内部会使用此
                        // 组装的update实例判断是否需要更新以做进一步工作
                        ApkUpdateVO data = FastJsonUtil.getBean(response, ApkUpdateVO.class);
                        Update update = new Update(response);
                        // 此apk包的更新时间
                        update.setUpdateTime(System.currentTimeMillis());
                        // 此apk包的下载地址
                        update.setUpdateUrl(data != null ? data.getDownloadUrl() : "");
                        // 此apk包的版本号
                        update.setVersionCode(data != null ? data.getVersionCode() : 0);
                        // 此apk包的版本名称
                        update.setVersionName(data != null ? data.getVersionName() : "");
                        // 此apk包的更新内容
                        update.setUpdateContent(data != null ? data.getContent() : "");
                        // 此apk包是否为强制更新
                        update.setForced("是".equals(data != null ? data.getIsForcedUpdate() : ""));
                        // 是否显示忽略此次版本更新按钮
                        update.setIgnore(false);
                        return update;
                    }
                })
                // 除了以上两个参数为必填。以下的参数均为非必填项。
                .checkCB(new UpdateCheckCB() {

                    @Override
                    public void onCheckError(Throwable t) {
//                        showToast("更新失败：code:" + t.getMessage());
                        LogUtils.e("更新失败：code:" + t.getMessage());
                    }

                    @Override
                    public void onUserCancel() {
                        LogUtils.e("用户取消更新");
                    }

                    @Override
                    public void onCheckIgnore(Update update) {
                        LogUtils.e("用户忽略此版本更新");
                    }

                    @Override
                    public void onCheckStart() {
                        // 此方法的回调所处线程异于其他回调。其他回调所处线程为UI线程。
                        // 此方法所处线程为你启动更新任务是所在线程
                        Utils.getMainHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                LogUtils.e("启动更新任务");
                            }
                        });
                    }

                    @Override
                    public void hasUpdate(Update update) {
                        LogUtils.e("检查到有更新");
                    }

                    @Override
                    public void noUpdate() {
                        //CustomDialog.nativeDialog(getApplicationContext(),"已经是最新版本");
                        LogUtils.e("无更新");
                    }
                })
                // apk下载的回调
                .downloadCB(new UpdateDownloadCB() {
                    @Override
                    public void onUpdateStart() {
                        LogUtils.e("下载开始");
                    }

                    @Override
                    public void onUpdateComplete(File file) {
                        LogUtils.e("下载完成");
                    }

                    @Override
                    public void onUpdateProgress(long current, long total) {
                    }

                    @Override
                    public void onUpdateError(Throwable t) {
                        LogUtils.e("下载失败:" + t.getMessage());
                    }
                });
    }

    /**
     * 极光推送初始化
     */
    private void initJPush() {
        JPushInterface.setDebugMode(isDeBug);    // 设置开启日志,发布时请关闭日志
        JPushInterface.init(this);            // 初始化 JPush
    }

   

    /**
     * 初始化定位sdk，建议在Application中创建
     */
    private void initBaiduLBS() {
        SDKInitializer.initialize(getApplicationContext());
        locationService = new LocationService(getApplicationContext());
    }

    /**
     * 初始化DBFlow数据库
     */
    private void initDBFlow() {
        FlowManager.init(new FlowConfig.Builder(this).build());
    }


    /**
     * 初始化日志工具
     */
    private void initLogUtils() {
        LogUtils.getLogConfig()
                .configAllowLog(isDeBug)        //是否允许输出日志
                .configFormatTag("%d{HH:mm:ss:SSS} %t %c{-5}")  //个性化设置Tag
                .configTagPrefix(getString(R.string.app_name))    //My'App'Name
                .configShowBorders(true)     //是否显示边界
                .configLevel(LogLevel.TYPE_ERROR); //日志等级
    }

    /**
     * 初始化okHttp工具
     */
    private void initOkHttpUtils() {


        OkHttpUtils.init(this);       //初始化工具

        OkHttpUtils.getInstance()
                .setConnectTimeout(TIME.CONNECT_TIMEOUT)            //全局的连接超时时间
                .setReadTimeOut(TIME.READ_TIMEOUT)                  //全局的读取超时时间
                .setWriteTimeOut(TIME.WRITE_TIMEOUT);                //全局的写入超时时间

        if (isDeBug)
            OkHttpUtils.getInstance().debug("OkHttpUtils");
    }



    /** Picasso 加载 */
    private class PicassoImageLoader implements NineGridView.ImageLoader {

        @Override
        public void onDisplayImage(Context context, ImageView imageView, String url) {
//            Picasso.with(context).load(url)//
//                    .placeholder(R.drawable.ic_default_image)//
//                    .error(R.drawable.ic_default_image)//
//                    .into(imageView);

            Glide.with(context)                             //配置上下文
                    .load(url)      //设置图片路径(fix #8,文件名包含%符号 无法识别和显示)
                    .error(R.mipmap.default_image)           //设置错误图片
                    .placeholder(R.mipmap.default_image)     //设置占位图片
                    .diskCacheStrategy(DiskCacheStrategy.ALL)//缓存全尺寸
                    .into(imageView);
        }

        @Override
        public Bitmap getCacheImage(String url) {
            return null;
        }
    }

    public static class GlideImageLoader implements ImageLoader {


        @Override
        public void displayImage(Activity activity, String path, ImageView imageView, int width, int height) {
            Glide.with(activity)                             //配置上下文
                    .load(Uri.fromFile(new File(path)))      //设置图片路径(fix #8,文件名包含%符号 无法识别和显示)
                    .error(R.drawable.bg_default)           //设置错误图片
                    .placeholder(R.drawable.bg_default)     //设置占位图片
                    .diskCacheStrategy(DiskCacheStrategy.ALL)//缓存全尺寸
                    .into(imageView);
        }

        public void displayImagePreview(Activity activity, String path, ImageView imageView, int width, int height) {

        }

        @Override
        public void clearMemoryCache() {

        }
    }

}
